﻿using System.Collections.Generic;
using TrueSync;

namespace HEFramework
{
    public static class SkillExecutionComponentSystem
    {
        [EntitySystem]
        public class SkillExecutionComponentAwakeSystem : AwakeSystem<SkillExecutionComponent>
        {
            protected override void Awake(SkillExecutionComponent _self)
            {
            }
        }

        [EntitySystem]
        public class SkillExecutionComponentUpdateSystem : UpdateSystem<SkillExecutionComponent>
        {
            protected override void Update(SkillExecutionComponent _self)
            {
                _self.TriggerPassiveSkill(eSkillTriggerType.OnUpdate, _self.GetMainEntity(), _self.GetMainEntityPos());
            }
        }

        public static void AddSkill(this SkillExecutionComponent _self, int _id)
        {
            var sc = _self.GetParent<SkillComponent>();
            var slc = _self.GetParentChild<SkillLockComponent>();
            var scd = _self.GetParentChild<SkillCooldownComponent>();
            if (sc == null || slc == null || scd == null)
            {
                return;
            }

            if (sc.SkillIDs.Contains(_id))
            {
                return;
            }

            sc.SkillIDs.Add(_id);
            slc.AddSkillLockData(_id);
            scd.AddSkillCooldownData(_id);
            _self.TriggerPassiveSkill(_id, eSkillTriggerType.OnAdd, _self.GetMainEntity(), _self.GetMainEntityPos());
        }

        public static void RemoveSkill(this SkillExecutionComponent _self, int _id)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var sc = _self.GetParent<SkillComponent>();
            var slc = _self.GetParentChild<SkillLockComponent>();
            var scd = _self.GetParentChild<SkillCooldownComponent>();

            if (dc == null || sc == null || slc == null || scd == null)
            {
                return;
            }

            sc.SkillIDs.Remove(_id);
            slc.RemoveSkillLockData(_id);
            scd.RemoveSkillCooldownData(_id);

            //TODO 执行销毁事件
            var skill = dc.LoadDataTable<DRSkill>().GetData(_id);
        }

        public static void TriggerActiveSkill(this SkillExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var sc = _self.GetParent<SkillComponent>();

            if (dc == null || sc == null)
            {
                return;
            }

            if (!sc.SkillIDs.Contains(_id))
            {
                return;
            }

            var spc = sc.GetChild<SkillPreparationComponent>();
            var scc = sc.GetChild<SkillCastComponent>();
            if (spc == null || scc == null)
            {
                return;
            }

            if (spc.Ready(_id, _receiver, _pos, true) == (int)eSkillErrorCode.None)
            {
                scc.Cast(_id, _receiver, _pos);
            }
        }

        public static void TriggerPassiveSkill(this SkillExecutionComponent _self, eSkillTriggerType _type, Entity _receiver, TSVector _pos)
        {
            var sc = _self.GetParent<SkillComponent>();
            if (sc == null)
            {
                return;
            }

            var skills = sc.SkillIDs;
            for (int i = 0; i < skills.Count; i++)
            {
                int id = skills[i];
                _self.TriggerPassiveSkill(id, _type, _receiver, _pos);
            }
        }

        public static void TriggerPassiveSkill(this SkillExecutionComponent _self, int _id, eSkillTriggerType _type, Entity _receiver, TSVector _pos)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var sc = _self.GetParent<SkillComponent>();

            if (dc == null || sc == null)
            {
                return;
            }

            if (!sc.SkillIDs.Contains(_id))
            {
                return;
            }

            var spc = sc.GetChild<SkillPreparationComponent>();
            if (spc == null)
            {
                return;
            }

            var table = dc.LoadDataTable<DRSkill>();
            var sData = table.GetData(_id);
            if (sData == null)
            {
                return;
            }

            if (sData.Type == (int)eSkillType.Passive || sData.Type == (int)eSkillType.Both)
            {
                if (sData.PTriggerType == (int)_type)
                {
                    if (spc.Ready(_id, _receiver, _pos, false) == (int)eSkillErrorCode.None)
                    {
                        //执行效果
                        _self.Execute(_id, _receiver, _pos, false);
                    }
                }
            }
        }

        public static void Execute(this SkillExecutionComponent _self, int _id, Entity _receiver, TSVector _pos, bool _isActive)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            if (dc == null)
            {
                return;
            }

            var scc = _self.GetParentChild<SkillCooldownComponent>();
            var src = _self.GetParentChild<SkillResourceComponent>();
            var sec = _self.GetParentChild<SkillEffectComponent>();

            if (scc == null || src == null || sec == null)
            {
                return;
            }


            var seec = sec.GetChild<SkillEffectExecutionComponent>();
            if (seec == null)
            {
                return;
            }

            using ListObject<int> ids = sec.GetEffectIDs(_id, _isActive);
            if (ids.Count <= 0)
            {
                return;
            }

            for (int i = 0; i < ids.Count; i++)
            {
                seec.Execute(ids[i], _receiver, _pos);
            }

            //进入冷却
            scc.SetSkillCooldown(_id, _isActive);
            //消耗资源
            src.Consume(_id, _isActive);
        }


        public static Entity GetMainEntity(this SkillExecutionComponent _self)
        {
            return _self.Parent.Parent;
        }

        public static TSVector GetMainEntityPos(this SkillExecutionComponent _self)
        {
            var entity = _self.GetMainEntity();
            var tc = entity.GetChild<TransformComponent>();
            if (tc == null)
            {
                return new TSVector();
            }

            return tc.P;
        }
    }
}